package edu.xmut.yuepaibackend.interceptor;

import cn.hutool.core.util.StrUtil;
import edu.xmut.yuepaibackend.model.dto.RedisUserDTO;
import edu.xmut.yuepaibackend.utils.*;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.MalformedJwtException;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import java.util.Objects;

import static edu.xmut.yuepaibackend.constant.RedisConstants.USER_INFO_KEY;
import static edu.xmut.yuepaibackend.utils.RCode.*;

@Slf4j
@Component
public class LoginHandlerInterceptor implements HandlerInterceptor {

    @Resource
    private RedisCacheUtils redisCacheUtils;


    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        String contextPath = request.getContextPath();
        String requestURI = request.getRequestURI();
        log.info("被访问，{}", requestURI.replace(contextPath, ""));
        String token = request.getHeader("Authorization");
        // 1.token为空，拦截，返回401
        if (StrUtil.isBlank(token)) {
            log.error("未登录");
            ServletUtils.sendJson(R.fail(TOKEN_NOT_EXIST, "未登录"), response);
            return false;
        }
        // 2.判断token是否有效，无效，返回401
        String userIdStr = "";
        try {
            Claims claims = JwtUtil.parseJWT(token);
            userIdStr = claims.getSubject();
        } catch (ExpiredJwtException e) {
            ServletUtils.sendJson(R.fail(TOKEN_EXPIRED, "Token已过期，请重新登录"), response);
            return false;
        } catch (MalformedJwtException e) {
            ServletUtils.sendJson(R.fail(TOKEN_INVALID, "非法Token"), response);
            return false;
        }
        // 3.查询redis中的用户实体，判断是否被踢下线
        String key = USER_INFO_KEY + userIdStr;
        RedisUserDTO user = redisCacheUtils.get(key);
        if (Objects.isNull(user)) {
            ServletUtils.sendJson(R.fail(TOKEN_EXPIRED, "Token已过期，请重新登录"), response);
            return false;
        }
        // 4.只允许同一账号在一个地方登录，判断是否被挤下线
        // if (!Objects.equals(user.getCurrentToken(), token)) {
        //     ServletUtils.sendJson(R.fail(LOGGED_IN_OTHER_DEVICE, "该账号已在其他地方登录"), response);
        //     return false;
        // }
        // 5.将用户id存入本地线程
        UserContext.setUserId(Long.valueOf(userIdStr));
        return true;
    }


    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        UserContext.remove();
    }
}
